import os
import tempfile
from time import time
from hashlib import sha256
import sqlite3
from sqlite3 import Error

import tornado
from streaming_form_data import StreamingFormDataParser
from streaming_form_data.targets import FileTarget, ValueTarget, SHA256Target
from tornado.ioloop import IOLoop
from tornado.web import Application, RequestHandler, stream_request_body


def db_connection():
    # to keep the __main__ tidy
    try:
        conn = sqlite3.connect('db.sqlite')
        return conn
    except Error as e:
        print(e)
    return None


class IndexHandler(tornado.web.RequestHandler):
    def get(self):
        self.render('index.html')

    def post(self):
        name = self.get_argument('name')
        surname = self.get_argument('surname')
        patronymic = self.get_argument('patronymic')
        comment = self.get_argument('comment')
        conn = db_connection()
        conn.execute(f"INSERT INTO profile (name, surname, patronymic, comment) VALUES ('{name}', '{surname}', '{patronymic}', '{comment}')")
        conn.commit()
        conn.close()
        self.render('index.html', returned=True)
        # 'returned' is used to show a message about successful form submission


GB = 1024 * 1024 * 1024


@stream_request_body
class UploadHandler(RequestHandler):
    def prepare(self):
        self.request.connection.set_max_body_size(2 * GB)
        # the default max file size is set to 2gb
        name = 'upload-{}'.format(int(time()))
        self.filename = os.path.join(tempfile.gettempdir(), name)
        self.file_ = FileTarget(self.filename)
        self._parser = StreamingFormDataParser(headers=self.request.headers)
        self._parser.register('file', self.file_)

    def data_received(self, chunk: bytes):
        self._parser.data_received(chunk)

    def post(self):
        self.render('load-finished.html', filename=self.file_.filename, sha256=sha256(open(self.filename, 'rb').read()).hexdigest())


class UploadPageHandler(RequestHandler):
    def data_received(self, chunk: bytes):
        pass

    def get(self):
        self.render('load.html')


def make_app():
    # to keep the __main__ tidy
    return tornado.web.Application([
        (r"/", IndexHandler),    # the name-surname form is the default page
        (r"/load", UploadPageHandler),
        (r"/upload", UploadHandler),
        ],
        template_path=os.path.join(os.path.dirname(__file__), "templates"),
        static_path=os.path.join(os.path.dirname(__file__), "static"),
    )


if __name__ == "__main__":
    app = make_app()
    app.listen(8888)
    tornado.ioloop.IOLoop.current().start()
